function NPlayer(playerId, fileChoserId, playListId, playControl, containerId) {
    var nPlayer = this;

    nPlayer.player = document.getElementById(playerId);
    nPlayer.fileChoser = document.getElementById(fileChoserId);
    nPlayer.container = containerId ? document.getElementById(containerId) : document;
    nPlayer.playList = document.getElementById(playListId);

    nPlayer.btnPause = document.getElementById(playControl.pause);
    nPlayer.btnPlay = document.getElementById(playControl.play);
    nPlayer.btnStop = document.getElementById(playControl.stop);

    nPlayer.current = null;
    nPlayer.mod = NPlayer.MOD_NORMAL;

    nPlayer.db = null;

    nPlayer.init();
}

NPlayer.prototype.openDb = function() {
    var nPlayer = this;

    if (window.webkitIndexedDB) {
	nPlayer.indexedDB = window.webkitIndexedDB;
	nPlayer.IDBTransaction=window.webkitIDBTransaction
    } else if (window.mozIndexedDB) {
	nPlayer.indexedDB = window.mozIndexedDB;
    }
    var request = nPlayer.indexedDB.open("nPlayer");
    request.onsuccess = function(e) {
	console.log('open db success')
	nPlayer.db = e.target.result;

	var version = '1.2';
	var db = nPlayer.db;

	db.onversionchange = function() {
	    console.log('Version Changed: ' + db.version)
	}
	//db.onerror = function(e) {
	//    console.log('db error: ' + e.target.webkitErrorMessage)
	//}
	//db.onabort = function(e) {
	//    console.log('db abort: ' + e.target.webkitErrorMessage)
	//}

	console.log('current version: ' + db.version)
	if (db.version == version) {
	    var setVRequest = db.setVersion(version);
	    setVRequest.onsuccess = function(e) {
		existStores = db.objectStoreNames
		for (var i = 0; i < existStores.length; i++) {
		    db.deleteObjectStore(existStores[i]);
		}
		var playList = db.createObjectStore('nPlayer_playList', 'ID',false);
		playList.createIndex('name', 'name');
		playList.createIndex('order', 'order');
		playList.createIndex('isDefault', 'isDefault');

		var songList = db.createObjectStore('nPlayer_songList','ID', false);
		songList.createIndex('playListID', 'playListID');
		songList.createIndex('name', 'name');
		songList.createIndex('order', 'order');

		var initData = {
		    'ID':'1',
		    'name': 'default',
		    'order': 1,
		    'isDefault': true
		}
		
		playList=db.transaction(['nPlayer_playList'],nPlayer.IDBTransaction.READ_WRITE).objectStore('nPlayer_playList');
		
		//the option in put should set to true if the key is autoIncrement
		playList.put(initData, initData['ID']).onerror=function(e){
		    console.log('init data error: '+e.target.webkitErrorMessage);
		}
		console.log('set version success. Current version: ' + db.version)
		console.log('data inited.')

	    }
	    setVRequest.onerror = function(e) {
		console.log('Set version failed.')
	    }
	    setVRequest.onblocked = function(e) {
		console.log('Set version blocked')
	    }
	}
    }
    request.onerror = function(e) {
	console.log('Open db failed.')
    }

}

NPlayer.prototype.MOD_NORMAL = 0
NPlayer.prototype.MOD_LOOPONE = 1
NPlayer.prototype.MOD_LOOPALL = 2

NPlayer.prototype.fileImplement = function(fileList) {
    var nPlayer = this;
    for (var i = 0; i < fileList.length; i++) {
	var reader = new FileReader();
	//need to research
	reader.onload = (function(file) {
	    return function(e) {
		nPlayer.addPlayList(file, e.target.result)
	    }
	})(fileList[i]);
	reader.onerror = function(e) {
	    switch (e.target.error.code) {
	    case e.target.error.NOT_FOUND_ERR:
		alert("file not found");
		break;
	    case e.target.error.SECURITY_ERR:
		alert('security error');
		break;
	    case e.target.error.NOT_READABLE_ERR:
		alert("file not readable");
		break;
	    case e.target.error.ABORT_ERR:
		alert("aborted");
		break;
	    case e.target.error.ENCODING_ERR:
		alert('encoding error');
		break;
	    default:
		alert('generic error: ' + e.target.error.code);
	    }
	}
	reader.readAsDataURL(fileList[i]);
    }
    var reader = new FileReader();
    reader.readAsDataURL(fileList[0]);
}
NPlayer.prototype.currentEnd = function() {
    var nPlayer = this;
    var nextSong = null;
    switch (nPlayer.mod) {
    case NPlayer.MOD_NORMAL:
	if (nPlayer.current.nextSibling) {
	    nextSong = nPlayer.current.nextSibling;
	}
	break;
    case NPlayer.MOD_LOOPONE:
	nextSong = nPlayer.current;
	break;
    case NPlayer.MOD_LOOPALL:
	if (nPlayer.current.nextSibling) {
	    nextSong = nPlayer.current.nextSibling;
	} else {
	    nextSong = nPlayer.playList.firstChild;
	}
	break;
    }
    if (nextSong) {
	nPlayer.setSong(nextSong);
	nPlayer.play(true);
    }
}
NPlayer.prototype.init = function() {
    var nPlayer = this;
    nPlayer.openDb();
    nPlayer.fileChoser.addEventListener('change', function(e) {
	nPlayer.fileImplement(e.target.files);
    }, false);
    nPlayer.btnPause.addEventListener('click', function(e) {
	e.stopPropagation();
	nPlayer.pause();
    }, false)
    nPlayer.btnPlay.addEventListener('click', function(e) {
	e.stopPropagation();
	nPlayer.play(false);
    }, false)
    nPlayer.btnStop.addEventListener('click', function(e) {
	e.stopPropagation();
	nPlayer.stop();
    }, false)
    nPlayer.container.addEventListener('dragenter', function(e) {
	e.stopPropagation();
	e.preventDefault();
    }, false)
    nPlayer.container.addEventListener('dragover', function(e) {
	e.stopPropagation();
	e.preventDefault();
    }, false)
    nPlayer.container.addEventListener('drop', function(e) {
	e.stopPropagation();
	e.preventDefault();
	nPlayer.fileImplement(e.dataTransfer.files);
    }, false)
    nPlayer.player.addEventListener('ended', function() {
	nPlayer.currentEnd();
    }, false)
}

NPlayer.prototype.addPlayList = function(file, url) {
    var nPlayer = this;

    var name = file.name;
    var size = file.size;
    var type = file.type;

    var songs = nPlayer.playList.getElementsByTagName('li');
    for (var i = 0; i < songs.length; i++) {
	if (songs[i].innerHTML == name) {
	    return;
	}
    }

    var playItem = document.createElement('li');
    playItem.filetype = type
    playItem.filesize = size
    playItem.fileurl = url
    playItem.innerHTML = name;
    playItem.addEventListener('dblclick', function(e) {
	e.stopPropagation();
	nPlayer.setSong(this);
	nPlayer.play(true);
    }, false)
    nPlayer.playList.appendChild(playItem);

    var dragSong = document.createElement('img');
    dragSong.setAttribute('src', 'img/gnome_audio_x_generic.png')
    var dragLine = document.createElement('div');
    dragLine.setAttribute('id', 'nPlayer_dragLine');

    playItem.setAttribute('draggable', 'true');
    playItem.addEventListener('dragstart', function(e) {
	e.stopPropagation();
	e.dataTransfer.setDragImage(dragSong, 25, 15)
    }, false)
    playItem.addEventListener('drag', function(e) {
	var dragSongNum = Math.round((e.clientY - nPlayer.pageY(nPlayer.playList)) / songs[0].offsetHeight);
	if (dragSongNum <= 0) {
	    nPlayer.playList.insertBefore(dragLine, songs[0]);
	} else if (dragSongNum < songs.length) {
	    nPlayer.playList.insertBefore(dragLine, songs[dragSongNum]);
	} else {
	    nPlayer.playList.appendChild(dragLine);
	}
    }, false)
    playItem.addEventListener('dragend', function(e) {
	if (dragLine.nextSibling) {
	    nPlayer.playList.insertBefore(playItem, dragLine.nextSibling);
	} else {
	    nPlayer.playList.appendChild(playItem);
	}
	nPlayer.playList.removeChild(dragLine);
    }, false)

    var btnDelPlayItem = document.createElement('div');
    btnDelPlayItem.innerHTML = 'x';
    btnDelPlayItem.className = 'nPlayer_btnDelPlayItem';
    btnDelPlayItem.addEventListener('click', function(e) {
	e.stopPropagation();
	nPlayer.delSong(this);
    }, false)
    playItem.appendChild(btnDelPlayItem);

    if (nPlayer.player.paused && !nPlayer.current) {
	nPlayer.setSong(playItem);
	nPlayer.play(true);
    }
}
NPlayer.prototype.delSong = function(delItem) {
    var nPlayer = this;
    delItem = delItem.parentNode;
    if (delItem == nPlayer.current) {
	nPlayer.currentEnd();
    }
    delItem.parentNode.removeChild(delItem);
}
NPlayer.prototype.setSong = function(playItem) {
    var nPlayer = this;
    if (nPlayer.current) {
	nPlayer.current.className = '';
    }
    playItem.className = 'current'
    nPlayer.current = playItem;
    nPlayer.player.setAttribute('src', playItem.fileurl);
}
NPlayer.prototype.play = function(isDelay) {
    var nPlayer = this;
    if (isDelay) {
	var playTimer = setInterval(function() {
	    nPlayer.player.play();
	    clearInterval(playTimer);
	}, 1000)
    } else {
	nPlayer.player.play();
    }
}
NPlayer.prototype.pause = function() {
    e.target.player.pause();
}
NPlayer.prototype.stop = function() {
    e.target.player.setAttribut('src', '');
}

NPlayer.prototype.pageY = function(ele) {
    var nPlayer = this;
    if (ele.offsetParent) {
	return ele.offsetTop + nPlayer.pageY(ele.offsetParent);
    } else {
	return ele.offsetTop;
    }
}

//No neccessary to use
NPlayer.prototype.hasClass = function(ele, cls) {
    return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
NPlayer.prototype.addClass = function(ele, cls) {
    var nPlayer = this;
    if (!nPlayer.hasClass(ele, cls)) {
	ele.className += ' ' + cls
    }
}
NPlayer.prototype.removeClass = function(ele, cls) {
    var nPlayer = this;
    if (nPlayer.hasClass(ele, cls)) {
	var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
	ele.className = ele.className.replace(reg, ' ');
    }
}